#ifndef __ARCHVALIDATOR_H__
#define __ARCHVALIDATOR_H__

#include "Validator.hpp"
#include "common.hpp"
#include <vector>

#define LUN 256

using namespace std;

/** \class ArchValidatorException
 *  \brief Eccezioni lanciate dalla classe ArchValidator. Contiene solo un messaggio di errore.
 */
class ArchValidatorException : public ValidatorException
{
    public:
    ArchValidatorException(char *mess) : ValidatorException(mess) {};
};

enum evaluation_type {
	AV_EVAL_SEQ,	//!<Valutazione sequenziale. L'ordine degli input viene preservato e la valutazione ripetuta una sola volta
	AV_EVAL_RND		//!<Valutazione in ordine casuale. Il numero di valutazioni dipende dal parametro "n_evals".
};

/** \class ArchValidator
 *  \brief Valutatore per l'implementazione di circuiti logici sequenziali e combinatori.
 *
 */
class ArchValidator : public Validator
{
#ifdef __DIST_ARCHVALIDATOR_H__
	friend class DistArchValidator;
#endif

	//!Insieme dei dati di validazione. I primi INPUT_SIGNALS costituiscono gli input, gli ultimi INPUT_SIGNALS rappresenstano le uscite.
	vector<HERAuint8*>data_vector;

    //!Massimo score ottenibile
    unsigned int max_score;

	evaluation_type evalT;

	//!Numero di valtazioni nel caso il tipo di valutazione di AV_EVAL_RND
	int n_eval;

	/** Modifica della posizione degli elementi di testing.
	 */
	void scrambleData();

public:
    //! Specifica del comportamento a fronte di errori durante la lettura dei settings
    enum error_hand_type{
        ERR_IGNORE,     //!< Ignora gli errori quando possibile
        ERR_HALT        //!< Lancia ArchValidatorException a fronte di qualsiasi errore
    };

    /** Legge i settings ed effettua le inizializzazioni necessarie
     *
     *  I parametri necessari per il costruttore sono:
     *  \arg \c train_set:
     *
     *  \param[in] settings Contiene tutti i parametri necessari per l'inizializzazione
     *  \param[in] eht Specifica il comportamento a fronte di un errore nella lettura dei parametri
     */
    ArchValidator(GAmodSettings &settings,error_hand_type eht = ArchValidator::ERR_HALT) throw(ArchValidatorException);

    /** Dealloca le strutture temporanee
     */
    ~ArchValidator();

    unsigned int valuta_pop(Popolazione *pop,stat_generation sg=Validator::STAT_ALL) throw(ArchValidatorException);
    unsigned int valuta_pop(Popolazione *pop,int eval_from = 0, int eval_to = 0,stat_generation sg=Validator::STAT_ALL) throw(ArchValidatorException);


    /** Restituisce le statistiche del valutatore
     *
     *  \param[out] settings Contenitore delle statistiche da ritornare
     */
    int getValutatorStats(GAmodSettings &settings) throw(ArchValidatorException) {return 0;};

    //! Ritorna il massimo punteggio ottenibile
    unsigned int getMaxScore() {return this->max_score;};

	unsigned int snapIndividuo(Individuo &Ind,char *path) throw(ArchValidatorException);
	//unsigned int print_single_run(Individuo &Ind, int *map, int *food, char *path) throw(EHW_Exception);

	int parseInputFile(string &filePath) throw(ArchValidatorException);

    //TODO: ArchValidator::getValutatorStats
};

#endif
